# -*- coding: utf-8 -*-

import ast

from ir.ir_helper import Helper, ClassHelper
from ir.ir_ds import ITypeStruct
from ir.ir_node import IVarReg

from .convert_type import convert_ast_to_type


def convert_pack(ast_pack: ast.ClassDef, helper: Helper):
    pack_name = ast_pack.name
    # Extract the member type by parsing the init method.
    ast_init = None
    for ast_line in ast_pack.body:
        # Pick out the function definition.
        if not isinstance(ast_line, ast.FunctionDef):
            continue
        # Check the name.
        if ast_line.name == '__init__':
            ast_init = ast_line
            break
    # Check the initial function definition.
    if ast_init is None:
        raise Exception('Failed to find the init function of Pack {}.'.format(pack_name))
    # Parse all the definition in the function definition.
    member_names = []
    member_types = []
    for ast_line in ast_init.body:
        if not isinstance(ast_line, ast.AnnAssign):
            raise Exception('Please specify the type of the value and initial value in Pack {}.'.format(pack_name))
        # Find out the type of the value.
        ast_target = ast_line.target
        # It should be an attribute which set to self.xxx.
        if not isinstance(ast_target, ast.Attribute) or \
                not isinstance(ast_target.value, ast.Name) or \
                not ast_target.value.id == 'self':
            raise Exception('All the assignment inside Pack should be "self.var_name: type = default_value"')
        # Append the member name.
        member_names.append(ast_target.attr)
        # Convert the ir type.
        member_types.append(convert_ast_to_type(ast_line.annotation, helper))
    # Create the structure type.
    ir_pack = ITypeStruct(pack_name, member_names, member_types)
    # Create the helper.
    helper_pack = ClassHelper()
    # Add helper for the structure, all the internal data would be treat as
    # registers.
    for var_name, var_type in zip(member_names, member_types):
        helper_pack.member[var_name] = IVarReg(var_name, var_type)
    # A is only taking care about the member.
    return [ir_pack], [helper_pack]